
using Opc.Ua;
using Sunny.UI;
using Sunny.UI.Win32;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data.SqlTypes;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using static Opc.Ua.TypeInfo;

namespace Motion.ZmcAct
{
    public enum Dir
    {
        Negative = -1,//负向
        Forward = 1//正向
    };
    public enum jogImageDirection
    {
        上,
        下,
        左,
        右,
        左上,
        右上,
        左下,
        右下
    };
    public enum AxisSpeed
    {
        Lowest = 0,
        Low,
        Middle,
        Hight,
    };
    public enum JogMode
    {
        Always = 1,//连续运动
        Step = 2,//定长
    };
    public class ZMC
    {
        public event EventHandler<Data> DataChanged;
        public event EventHandler<ArrayData> ArrayDataChanged;
        public static ZMC Instance { get; private set; } = new ZMC();

        public bool IsLink { get; set; } = false;
        private IntPtr phandle;

        private List<Data> DataReadList;
        private List<ArrayData> ArrayDataReadList;
        private string sIP;

        private byte[] psResponse = new byte[100];

        private bool bBreakF;

        object LockZmc { get; set; }
        object LockDataRead { get; set; }


        public void WriteArray(string varName, List<float> list)
        {
            lock (LockZmc)
            {
                if (phandle == (IntPtr)0)
                {
                    return;
                }
                zmcaux.ZAux_Direct_SetUserArray(phandle, varName, 0, list.Count, list.ToArray());		//发送数据
            }

        }
        public void WriteUserVar(string varName, float var1)
        {
            lock (LockZmc)
            {
                if (phandle == (IntPtr)0)
                {
                    return;
                }
                zmcaux.ZAux_Direct_SetUserVar(phandle, varName, var1);                //发送命令
            }
        }
        public void ReadArray(string varName, int count, out List<float> list)
        {
            lock (LockZmc)
            {
                list = null;
                if (phandle == (IntPtr)0)
                {
                    return;
                }
                float[] m_ArrayShow = new float[count];

                zmcaux.ZAux_Direct_GetUserArray(phandle, varName, 0, count, m_ArrayShow);       //发送数据
                list = new List<float>(m_ArrayShow);
            }
        }

        public void ReadArrayIndex(string varName, int index, out float val)
        {
            lock (LockZmc)
            {
                val = 0f;
                if (phandle == (IntPtr)0)
                {
                    return;
                }
                float[] m_ArrayShow = new float[1];

                zmcaux.ZAux_Direct_GetUserArray(phandle, varName, index, 1, m_ArrayShow);       //发送数据
                val = m_ArrayShow[0];
            }
        }
        public void WriteArrayIndex(string varName, int index,  float val)
        {
            lock (LockZmc)
            {
                //val = 0f;
                if (phandle == (IntPtr)0)
                {
                    return;
                }
                float[] m_ArrayShow = new float[1];
                m_ArrayShow[0] = val;
                zmcaux.ZAux_Direct_SetUserArray(phandle, varName, index, 1, m_ArrayShow);       //发送数据
            }
        }
        public void ReadUserVar(string varName, out float var1)
        {
            lock (LockZmc)
            {
                var1 = 0;
                if (phandle == (IntPtr)0)
                {
                    return;
                }
                zmcaux.ZAux_Direct_GetUserVar(phandle, varName, ref var1);          //读取全局变量
            }
        }
        public float GetAxisPos(int axisId)
        {
            if (phandle == (IntPtr)0)
            {
                return 0;
            }
            float fx = 0;
            int rtn = 0;
            rtn = zmcaux.ZAux_Direct_GetDpos(phandle, axisId, ref fx);

            if (0 != rtn)
            {
                phandle = IntPtr.Zero;
                return 0;
            }
            return fx;
        }
        public float GetAxisEncoderPos(int axisId)
        {
            if (phandle == (IntPtr)0)
            {
                return 0;
            }
            float fx = 0;
            int rtn = 0;
            rtn = zmcaux.ZAux_Direct_GetEncoder(phandle, axisId, ref fx);

            if (0 != rtn)
            {
                phandle = IntPtr.Zero;
                return 0;
            }
            return fx;
        }
        public bool IsAxisStop(int axisId)
        {
            if (phandle == (IntPtr)0)
            {
                return false;
            }

            int st1 = 0;
            int rtn = 0;
            rtn = zmcaux.ZAux_Direct_GetIfIdle(phandle, axisId, ref st1);

            const int stopFlag = -1;
            return st1 == stopFlag;
        }

        public bool ReadInput(int index)
        {
            if (phandle == (IntPtr)0)
            {
                return false;
            }
            uint val = 0;
            int rtn = 0;
            rtn = zmcaux.ZAux_Direct_GetIn(phandle, index, ref val);
            if (0 != rtn)
            {
                phandle = IntPtr.Zero;
                return false;
            }
            return val == 1;
        }

        public bool ReadOutput(int index)
        {
            if (phandle == (IntPtr)0)
            {
                return false;
            }
            uint val = 0;
            int rtn = 0;
            rtn = zmcaux.ZAux_Direct_GetOp(phandle, index, ref val);
            if (0 != rtn)
            {
                phandle = IntPtr.Zero;
                return false;
            }
            return val == 1;
        }

        public void WriteOutput(int index, bool val)
        {
            if (phandle == (IntPtr)0)
            {
                return;
            }
            int rtn = 0;
            rtn = zmcaux.ZAux_Direct_SetOp(phandle, index, val ? (uint)1 : 0);
            if (0 != rtn)
            {
                phandle = IntPtr.Zero;
                return;
            }
        }
        public void JogAxis(int axisIndex, Dir jogDirection, JogMode mode, AxisSpeed speed, double dis)
        {
            ZMC zmc = ZMC.Instance;
            zmc.ReadUserVar("gv_InitStatus", out float InitStatus);
            //if (InitStatus == 1)
            //{
                WriteUserVar("g_aAxisNum", axisIndex);
                WriteUserVar("g_aAxisDir", (int)jogDirection);
                WriteUserVar("g_aAxisMode", (int)mode);
                WriteUserVar("g_aAxisSpeed", (int)speed);
                WriteUserVar("g_aAxisDis", (float)(dis));
                WriteUserVar("g_aAxisTrigger", 1);
            //}
            //else
            //{
               // UIMessageTip.Show("请先复位机台");
            //}
            
        }

        public void JogStop(int axisIndex)
        {
            WriteUserVar("g_aAxisNum", axisIndex);
            WriteUserVar("g_aAxisSTrigger", 1);
        }
        public Task task { get; set; }


        private ZMC()
        {
            LockZmc = new object();
            LockDataRead = new object();

            DataReadList = new List<Data>();
            ArrayDataReadList = new List<ArrayData>();
        }

        public int Connect(string IP)
        {

            sIP = IP;
            if (IP == null || IP == string.Empty)
            {
                return -1;
            }
            if (!Regex.IsMatch(IP, "[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}"))
            {
               // MessageBox.Show("请输入一个正确的IP地址");
                return -1;
            }
            if (IsLink)
            {
                Break();
            }
            int i = zmotion.ZMC_OpenEth(IP, out phandle);
            if (i == 0)
            {
                IsLink = true;
            }
            else
            {
                IsLink = false;
            }
            if (IsLink)
            {
                bBreakF = false;
                task = new Task(delegate
                {

                    while (!bBreakF)
                    {
                        ReadData();
                        Thread.Sleep(10);
                    }
                });
                task.Start();
            }
            return i;
        }

        public void Break()
        {
            bBreakF = true;
            if (task != null)
            {
                task.Wait(1000);
            }
            try
            {
                if (phandle != IntPtr.Zero)
                {
                    zmotion.ZMC_Close(phandle);
                  
                }
            }
            catch (Exception)
            {

            }
            phandle = IntPtr.Zero;

        }
        public void AddDataRead(string varName)
        {
            lock (LockDataRead)
            {
                if (DataReadList.First(x => x.VarName == varName) != null)
                {
                    DataReadList.Add(new Data()
                    {
                        VarName = varName,
                    });
                }
            }
        }
        public void AddArrayDataRead(string varName)
        {
            lock (LockDataRead)
            {
                if (ArrayDataReadList.First(x => x.VarName == varName) != null)
                {
                    ArrayDataReadList.Add(new ArrayData()
                    {
                        VarName = varName,
                    });
                }
            }
        }


        public void ReadData()
        {
            lock (LockDataRead)
            {
                foreach (var item in DataReadList)
                {
                    if (!string.IsNullOrEmpty(item.VarName))
                    {
                        ReadUserVar(item.VarName, out float var1);
                        if (item.Value != var1)
                        {
                            item.Value = var1;
                            DataChanged?.Invoke(this, new Data()
                            {
                                VarName = item.VarName,
                                Value = item.Value,
                            });
                        }
                    }
                }
                foreach (var item in ArrayDataReadList)
                {
                    if (!string.IsNullOrEmpty(item.VarName))
                    {
                        ReadArrayIndex(item.VarName, item.Index, out float var1);
                        if (item.Value != var1)
                        {
                            item.Value = var1;
                            ArrayDataChanged?.Invoke(this, new ArrayData()
                            {
                                VarName = item.VarName,
                                Value = item.Value,
                                Index = item.Index,
                            });
                        }
                    }
                }
            }

        }

    }
}